package com.tgb.lk.autossh;

import java.io.File;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.apache.velocity.VelocityContext;
import com.tgb.lk.annotation.AutoBean;
import com.tgb.lk.annotation.AutoField;
import com.tgb.lk.config.Config;
import com.tgb.lk.config.ConfigXmlUtil;
import com.tgb.lk.table.Log;
import com.tgb.lk.table.TableConfig;
import com.tgb.lk.util.AppConstants;
import com.tgb.lk.util.CharUtil;
import com.tgb.lk.util.ClassLoaderUtil;
import com.tgb.lk.util.FileUtil;
import com.tgb.lk.util.ManageClassLoader;
import com.tgb.lk.util.VelocityUtill;

public class AutoMain {
	public void generate() {
		ConfigXmlUtil util = new ConfigXmlUtil();
		Config config = util.getConfig();
		if (config != null) {
			System.out.println("config info:" + config);

			// //方式一:读取路径,并根据路径自动算出包名,加载出所有的类,存在bug:在根文件夹下不仅有实体类,还有很多接口和其他实现类,这样导致报错.
			// Set<Class<?>> classes = PackageUtil.getClassesFromPath(config
			// .getBeansDir());
			// Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
			List<Class<?>> classes = new ArrayList<Class<?>>();
			try {
				// 将配置在libs文件夹中的jar加载到环境中.
				List<String> jarFiles = FileUtil.getAllFiles(
						config.getLibsDir(), null);
				for (String file : jarFiles) {
					if (file.toLowerCase().endsWith(".jar")) {
						ClassLoaderUtil.addClassPath(file);
					}
				}
				// // 方式二:
				// ClassLoaderUtil.addClassPath(config.getBeansDir());
				// classes = PackageUtil.getClasses(config.getBeansPackage(),
				// null, config.getBeansDir());

				// 方式三:支持修改后重新加载class
				String path = config.getBeansDir();
				ManageClassLoader mc = new ManageClassLoader();
				classes = mc.loadClass(path);
				System.out.println(classes);
			} catch (Exception e) {
				Log.log(e);
				e.printStackTrace();
			}

			VelocityUtill velocityUtill = new VelocityUtill();
			VelocityContext ctx = velocityUtill.getVelocityContext();

			Log.log("beans:" + classes, 4);

			List<Bean> beans = new ArrayList<Bean>();
			for (Class<?> clazz : classes) {
				String name = clazz.getSimpleName();// 获得类名
				Bean bean = new Bean();
				bean.setName(CharUtil.toLowerCaseFirstOne(name));
				bean.setKey("id");// 设置默认为字符串"id".
				if (clazz.isAnnotationPresent(AutoBean.class)) {
					AutoBean autoBean = (AutoBean) clazz
							.getAnnotation(AutoBean.class);
					if (!"".equals(autoBean.alias().trim())) {
						bean.setAlias(autoBean.alias());
					}
					bean.setTable(autoBean.table());
					bean.setArgs(autoBean.args());
				}
				Field[] fields = clazz.getDeclaredFields();
				BeanField[] beanFields = new BeanField[fields.length];
				for (int i = 0; i < fields.length; i++) {
					Field field = fields[i];
					beanFields[i] = new BeanField();
					beanFields[i].setName(field.getName());
					beanFields[i].setKey(false);
					beanFields[i].setRequired(false);
					beanFields[i].setType(field.getType().getSimpleName());

					if (field.isAnnotationPresent(AutoField.class)) {
						AutoField autoField = (AutoField) field
								.getAnnotation(AutoField.class);
						if (!"".equals(autoField.alias().trim())) {
							beanFields[i].setAlias(autoField.alias());
						}
						if (autoField.isKey()) {
							beanFields[i].setKey(true);
							bean.setKey(field.getName());// isKey为true时设置.
						}
						beanFields[i].setRequired(autoField.isRequired());
						beanFields[i].setCombo(autoField.combo());
						beanFields[i].setArgs(autoField.args());
						beanFields[i].setColumn(autoField.column());
						if (!"".equals(autoField.type())) {
							beanFields[i].setType(autoField.type());
						}
						if (!"".equals(autoField.columnType())) {
							beanFields[i].setColumnType(autoField.columnType());
						}
						beanFields[i].setLength(autoField.length());
					}
					bean.setFields(beanFields);
				}
				if (config.isChkDBSource()) {// 从数据库表读取数据放入模板变量.
					bean.setDatas(DBExcelDataUtil.getDataFromDB(clazz));
				}
				beans.add(bean);
			}
			setCtxConfig(config, ctx);// 加入自定义的键值配置.
			ctx.put("beans", beans);
			String basePackagePath = String.valueOf(ctx.get("base-package"))
					.replace(".", File.separator);
			try {
				ctx.put("date", (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date()));
				// 拷贝固定文件.
				FileUtil.copyFolder(config.getFixedFilesDir(), makeFilePath(""));
				Log.log(config.getFixedFilesDir() + " generate complate", 1);

				// 生成类
				List<String> files = FileUtil.getAllFiles(
						config.getTemplatesDir(), null);
				for (String file : files) {
					for (Bean bean : beans) {
						ctx.put("bean", bean);
						String tempPath = file.replace(
								config.getTemplatesDir(),
								config.getDestCodeDir());
						tempPath = tempPath.replace("${base-package}",
								basePackagePath.trim());
						tempPath = tempPath.replace("${bean}", bean.getName())
								.replace("${bean.name}", bean.getName())
								.replace("${bean.Uname}", bean.getUname())
								.replace("${bean.Lname}", bean.getLname())
								.replace("${bean.ALname}", bean.getALname())
								.replace("${bean.AUname}", bean.getAUname());
						try {
							VelocityUtill.write(ctx, file, tempPath);
						} catch (Exception e) {
							Log.log(e);
							e.printStackTrace();
						}
					}
				}
				// createModel(classes, config);
				// // 过滤掉注解字段 @AutoField( 的行.
				// FileUtil.copyFileByLines(config.getBeansDir(),
				// makeFilePath("src/"), new String[] { "@AutoField(",
				// ".annotation.*" });
				Log.log(config.getBeansDir() + " generate complate", 1);

				// 生成readme.txt
				// VelocityUtill.write(ctx, "config/readme.txt",
				// makeFilePath("readme.txt"));

			} catch (Exception e) {
				Log.log(e);
				e.printStackTrace();
			}
			Log.log("代码生成完毕,代码生成位置:" + makeFilePath(""), 3);
		}
	}

	public void setCtxConfig(Config config, VelocityContext ctx) {
		String str = config.getCtxConfig();
		String ctxConfigs[] = str.split("\n");
		for (String ctxConfig : ctxConfigs) {
			try {
				String[] keys = ctxConfig.split("=");
				ctx.put(keys[0].trim(), keys[1].trim());
			} catch (Exception e) {
				Log.log("注入模板的键值" + ctxConfig + "有误,请检查", 3);
				continue;
			}
		}
	}

	// public void generate_oldbak() {
	// ConfigXmlUtil util = new ConfigXmlUtil();
	// Config config = util.getConfig();
	// if (config != null) {
	// System.out.println("config info:" + config);
	//
	// // //从package中加载.
	// // Set<Class<?>> classes = PackageUtil.getClasses(config
	// // .getBeanPackage());
	// VelocityUtill velocityUtill = new VelocityUtill();
	// VelocityContext ctx = velocityUtill.getVelocityContext();
	//
	// ClassLoaderUtil.addClassPath(config.getBeanFilesDir());
	// List<String> jarFiles = FileUtil.getAllFiles(config.getLibsDir(),
	// null);
	// for (String file : jarFiles) {
	// if (file.endsWith(".jar")) {
	// ClassLoaderUtil.addClassPath(file);
	// }
	// }
	// ClassLoaderUtil.addClassPath(config.getLibsDir() + File.separator
	// + "tools.jar");
	// ClassLoaderUtil.listSystemClassPath();
	// Set<Class<?>> classes = FileUtil.getClassfromJava(config
	// .getBeanFilesDir(), null);
	// Log.log("bean package classes:" + classes, 1);
	//
	// String modelPath = config.getDestModelPackage().replace(".",
	// File.separator);
	//
	// List<Bean> beans = new ArrayList<Bean>();
	// for (Class<?> clazz : classes) {
	// String name = clazz.getSimpleName();// 获得类名
	// Bean bean = new Bean();
	// bean.setUname(name);
	// bean.setName(CharUtil.toLowerCaseFirstOne(name));
	// // bean.setPath(modelPath);
	// bean.setKey("id");// 设置默认为字符串"id".
	// Field[] fields = clazz.getDeclaredFields();
	// BeanField[] beanFields = new BeanField[fields.length];
	// for (int i = 0; i < fields.length; i++) {
	// Field field = fields[i];
	// beanFields[i] = new BeanField();
	// beanFields[i].setName(field.getName());
	// beanFields[i].setKey(false);
	// beanFields[i].setRequired(false);
	// if (field.isAnnotationPresent(AutoField.class)) {
	// AutoField autoField = (AutoField) field
	// .getAnnotation(AutoField.class);
	// if (!autoField.alias().trim().equals("")) {
	// beanFields[i].setAlias(autoField.alias());
	// }
	// if (autoField.isKey()) {
	// beanFields[i].setKey(true);
	// bean.setKey(field.getName());// isKey为true时设置.
	// }
	// beanFields[i].setRequired(autoField.isRequired());
	// beanFields[i].setCombo(autoField.combo());
	// beanFields[i].setType(autoField.type());
	// }
	// bean.setFields(beanFields);
	// }
	// beans.add(bean);
	// }
	//
	// ctx.put("beans", beans);
	// try {
	// // 拷贝固定文件.
	// FileUtil
	// .copyFolder(config.getFixedFilesDir(), makeFilePath(""));
	// Log.log(config.getFixedFilesDir() + " generate complate", 1);
	//
	// // 生成配置文件
	// VelocityUtill.write(ctx, config.getActionConfig(),
	// makeFilePath("src/"
	// + getFileName(config.getActionConfig())));
	// Log.log(config.getActionConfig() + " generate complate", 1);
	//
	// VelocityUtill.write(ctx, config.getDaoConfig(),
	// makeFilePath("src/"
	// + getFileName(config.getDaoConfig())));
	// Log.log(config.getDaoConfig() + " generate complate", 1);
	//
	// VelocityUtill.write(ctx, config.getMgrConfig(),
	// makeFilePath("src/"
	// + getFileName(config.getMgrConfig())));
	// Log.log(config.getMgrConfig() + " generate complate", 1);
	//
	// VelocityUtill.write(ctx, config.getCommonConfig(),
	// makeFilePath("src/"
	// + getFileName(config.getCommonConfig())));
	// Log.log(config.getCommonConfig() + " generate complate", 1);
	//
	// VelocityUtill.write(ctx, config.getStrutsConfig(),
	// makeFilePath("src/"
	// + getFileName(config.getStrutsConfig())));
	// Log.log(config.getStrutsConfig() + " generate complate", 1);
	//
	// VelocityUtill.write(ctx, config.getHibernateConfig(),
	// makeFilePath("src/"
	// + getFileName(config.getHibernateConfig())));
	// Log.log(config.getHibernateConfig() + " generate complate", 1);
	//
	// // 生成类
	// for (Bean bean : beans) {
	// // String modelPath1 = "src/" +
	// // config.getDestModelPackage().replace(".",
	// // "/")+"/"+bean.getUname()+".java";
	// String actionPath = "src/"
	// + config.getDestActionPackage().replace(".", "/")
	// + "/" + bean.getUname() + "Action.java";
	// String mgrPath = "src/"
	// + config.getDestMgrPackage().replace(".", "/")
	// + "/" + bean.getUname() + "Mgr.java";
	// String mgrImplPath = "src/"
	// + config.getDestMgrPackage().replace(".", "/")
	// + "/impl/" + bean.getUname() + "MgrImpl.java";
	// String daoPath = "src/"
	// + config.getDestDaoPackage().replace(".", "/")
	// + "/" + bean.getUname() + "Dao.java";
	// String daoImplPath = "src/"
	// + config.getDestDaoPackage().replace(".", "/")
	// + "/impl/" + bean.getUname() + "DaoImpl.java";
	// String hbmPath = "src/"
	// + config.getDestModelPackage().replace(".", "/")
	// + "/" + bean.getUname() + ".hbm.xml";
	//
	// ctx.put("bean", bean);
	// VelocityUtill.write(ctx, config.getAction(),
	// makeFilePath(actionPath));
	// Log.log(bean.getName() + config.getAction()
	// + " generate complate", 1);
	//
	// VelocityUtill.write(ctx, config.getMgr(),
	// makeFilePath(mgrPath));
	// Log.log(bean.getName() + config.getMgr()
	// + " generate complate", 1);
	//
	// VelocityUtill.write(ctx, config.getMgrImpl(),
	// makeFilePath(mgrImplPath));
	// Log.log(bean.getName() + config.getMgrImpl()
	// + " generate complate", 1);
	//
	// VelocityUtill.write(ctx, config.getDao(),
	// makeFilePath(daoPath));
	// Log.log(bean.getName() + config.getDao()
	// + " generate complate", 1);
	//
	// VelocityUtill.write(ctx, config.getDaoImpl(),
	// makeFilePath(daoImplPath));
	// Log.log(bean.getName() + config.getDaoImpl()
	// + " generate complate", 1);
	//
	// VelocityUtill.write(ctx, config.getHibernateHbmConfig(),
	// makeFilePath(hbmPath));
	// Log.log(bean.getName() + config.getHibernateHbmConfig()
	// + " generate complate", 1);
	//
	// String addJsp = "WebRoot/" + bean.getName() + "/"
	// + bean.getName() + "_add.jsp";
	// String updateJsp = "WebRoot/" + bean.getName() + "/"
	// + bean.getName() + "_update.jsp";
	// String listJsp = "WebRoot/" + bean.getName() + "/"
	// + bean.getName() + "_list.jsp";
	//
	// VelocityUtill.write(ctx, config.getAddJsp(),
	// makeFilePath(addJsp));
	// Log.log(bean.getName() + config.getAddJsp()
	// + " generate complate", 1);
	//
	// VelocityUtill.write(ctx, config.getUpdateJsp(),
	// makeFilePath(updateJsp));
	// Log.log(bean.getName() + config.getUpdateJsp()
	// + " generate complate", 1);
	//
	// VelocityUtill.write(ctx, config.getListJsp(),
	// makeFilePath(listJsp));
	// Log.log(bean.getName() + config.getListJsp()
	// + " generate complate", 1);
	//
	// List<String> files = FileUtil.getAllFiles(config
	// .getOthersDir(), null);
	// for (String file : files) {
	// // File file2 = new File(file);
	// String tempPath = file.replace(config.getOthersDir(),
	// config.getDestCodeDir()).replace("${bean}",
	// bean.getName()).replace("${bean.name}",
	// bean.getName()).replace("${bean.Uname}",
	// bean.getUname());
	// VelocityUtill.write(ctx, file, tempPath);
	// }
	//
	// /*
	// * VelocityUtill.write(ctx, config.getFixedFilesDir() +
	// * "/WebRoot/left.jsp", makeFilePath("WebRoot/left.jsp"));
	// */
	// }
	// createModel(classes, config);
	// // 过滤掉注解字段 @AutoField( 的行.
	// FileUtil.copyFileByLines(config.getBeanFilesDir(),
	// makeFilePath("src/"), new String[] { "@AutoField(",
	// ".annotation.*" });
	// Log.log(config.getBeanFilesDir() + " generate complate", 1);
	//
	// // 生成readme.txt
	// VelocityUtill.write(ctx, "config/readme.txt",
	// makeFilePath("readme.txt"));
	//
	// } catch (Exception e) {
	// e.printStackTrace();
	// }
	// Log.log("===代码生成完毕,代码生成位置:" + makeFilePath(""), 3);
	// }
	// }

	public void createModel(Set<Class<?>> classes, Config config) {
		for (Class<?> clazz : classes) {
			StringBuffer head = new StringBuffer(2000);
			String name = clazz.getSimpleName();// 获得类名
			Field[] fields = clazz.getDeclaredFields();

			head.append("package ").append(clazz.getPackage()).append(";\n\n");
			head.append("import java.util.*;\n");
			head.append("\n");
			head.append("public class ").append(name).append(" {\n");
			for (Field field : fields) {
				head.append("  private ")
						.append(field.getType().getSimpleName()).append(" ")
						.append(field.getName()).append(";\n");
				head.append("  public ")
						.append(field.getType().getSimpleName()).append(" get")
						.append(CharUtil.toUpperCaseFirstOne(field.getName()))
						.append("(){\n").append("    return ")
						.append(field.getName()).append(";").append("\n  }\n");
				head.append("  public void").append(" set")
						.append(CharUtil.toUpperCaseFirstOne(field.getName()))
						.append("(").append(field.getType().getSimpleName())
						.append(" ").append(field.getName()).append("){\n")
						.append("    this.").append(field.getName())
						.append("=").append(field.getName()).append(";")
						.append("\n  }\n\n");
			}

			head.append("\n}");
			Log.writeFile(
					head.toString(),
					makeFilePath("/src/"
							+ config.getBeansPackage().replace(".", "/") + "/"
							+ clazz.getSimpleName() + ".java"), false);
		}
	}

	private String getFileName(String path) {
		return new File(path).getName();
	}

	public String makeFilePath(String file) {
		ConfigXmlUtil util = new ConfigXmlUtil();
		Config config = util.getConfig();
		if (config != null) {
			if (!config.getDestCodeDir().contains(":")) {
				file = AppConstants.BASE_PATH + config.getDestCodeDir() + "/"
						+ file;
			} else {
				file = config.getDestCodeDir() + "/" + file;
			}
			file = file.replace("/", File.separator).replace("\\",
					File.separator);
		}
		String dirPath = file.substring(0, file.lastIndexOf(File.separator));
		File dirFile = new File(dirPath);

		if (!dirFile.exists()) {
			if (!dirFile.mkdirs()) {
				throw new RuntimeException(dirFile + "文件夹创建失败");
			}
		}
		return file;
	}

	public static void main(String[] args) {
		run();
	}

	public static void run() {
		AutoMain autoMain = new AutoMain();
		autoMain.generate();
	}

	public static void compileJava() {

		ConfigXmlUtil util = new ConfigXmlUtil();
		Config config = util.getConfig();
		List<String> jarFiles = FileUtil.getAllFiles(config.getLibsDir(), null);
		for (String file : jarFiles) {
			if (file.toLowerCase().endsWith(".jar")) {
				ClassLoaderUtil.addClassPath(file);
			}
		}
		TableConfig tConfig = TableConfig.getInstance();
		ClassLoaderUtil.addClassPath(tConfig.getPath());
		ClassLoaderUtil.addClassPath(config.getBeansDir());
		ClassLoaderUtil.addClassPath(config.getLibsDir());
		// Set<Class<?>> classes = FileUtil.getClassfromJava(tConfig.getPath(),
		// null);
		// Log.log("compile java to class:" + classes, 4);

		String path = FileUtil.filterDir(tConfig.getPath());
		File a = new File(path);
		String[] file = a.list();
		File temp = null;
		if (file == null || file.length == 0) {
			Log.log("*.java files not found!", 3);
			return;
		}
		String destPath = FileUtil.filterDir(config.getBeansDir());
		for (int i = 0; i < file.length; i++) {
			temp = new File(path + File.separator + file[i]);
			if (temp.isFile() && temp.getName().endsWith(".java")) {
				FileUtil.compiler(temp.getAbsolutePath());

				FileUtil.copyFile(
						temp.getAbsolutePath().replace(".java", ".class"),
						destPath + File.separator
								+ temp.getName().replace(".java", ".class"));
			}
		}

	}
}
